#include "TOTAL.h"

TOTAL_T* TOTAL_t;



//************************************
// Method:    	CALCU_SAMA						//< SAMA运算函数
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	bool							//< 成功：true；失败：false
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	float dt						//< 运算周期
// Parameter: 	bool * DI						//< 数字量输入值数组指针
// Parameter: 	bool * DO						//< 数字量输出值数组指针
// Parameter: 	bool * AI						//< 模拟量输入值数组指针
// Parameter: 	bool * AO						//< 模拟量输出值数组指针
//************************************
bool CALCU_SAMA(TOTAL)(Model_Base_t* arg, float dt, bool* DI, bool* DO, float* AI, float* AO)
{
#define max(a, b)	(((a) > (b)) ? (a) : (b))
#define min(a, b)	(((a) > (b)) ? (b) : (a))
	/****************变量定义区开始**************/
	/*<<<<<定义输入变量>>>>>*/
	bool Sd;					//< 置位信号
	float Input_Value;			//< 输入值
	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/*<<<<<定义输出变量>>>>>*/
	float Calu_Value = 0;			//< 当前积算值
	//< float LastCalu_Value = 0;	//< 上次积算值				duan0831
	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/*<<<<<定义参数变量>>>>>*/
	float Init_Value;			//< 积算初值
	float K;					//< 转换系数
	TOTAL_WORK_t mode;			//< 积算方式
	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/*<<<<<定义中间变量>>>>>*/
	bool* Sd_Last;				//< 上一时刻置位信号
	bool* Start_Flg;			//< 开始积算的标志
	float* AI_Last;				//< 上一时刻输入值
	float* Sum_Value;			//< 输入值累加
	int* Sum_Count;				//< 输入数量累加
	float* LastOut_Value;		//< 上一时刻输出值
	float* LastCalu_Value;		//< 上次积算值
	/*<<<<<<<<<<<<<<<<<<<<<<*/
	
	/****************变量定义区结束**************/

	NAME(TOTAL)* Obj = (NAME(TOTAL)*)arg;

	/****************变量赋值**************/
	/*<<<<<输入变量赋值>>>>>*/
	Sd = DI[0];
	Input_Value = AI[0];
	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/*<<<<<参数变量赋值>>>>>*/
	Init_Value = Obj->Par.Init_Value;
	K = Obj->Par.K;
	mode = Obj->Par.mode;
	/*<<<<<<<<<<<<<<<<<<<<<<*/

	/*<<<<<中间变量赋值（由于中间变量属于静态变量，其数值要随运算而更新，
	因此此处建议将中间变量的地址赋值给相应变量，省去了运算完成后再次赋值
	给中间变量的过程）>>>>>*/
	Sd_Last = &(Obj->Sta.Sd_Last);
	Start_Flg = &(Obj->Sta.Start_Flg);
	AI_Last = &(Obj->Sta.AI_Last);
	Sum_Value = &(Obj->Sta.Sum_Value);
	Sum_Count = &(Obj->Sta.Sum_Count);
	LastOut_Value = &(Obj->Sta.LastOut_Value);
	LastCalu_Value = &(Obj->Sta.LastCalu_Value);

	/*<<<<<<<<<<<<<<<<<<<<<<*/
	//< LastOut_Value = Obj->Base.Out.AO[0];		duan0831
	/**************变量赋值结束************/

	/********************************************/
	/**************算法功能实现开始**************/
	/********************************************/
	if (Start_Flg[0] == true)
	{
		switch (mode)
		{
		case TOTAL_SUM:
			Calu_Value = LastOut_Value[0] + K * Input_Value;
			break;
		case TOTAL_AVG:
			Sum_Value[0] += K * Input_Value;
			Sum_Count[0]++;
			if (Sum_Count[0] >= 1E8)
				Sum_Count[0] = 1E8;
			Calu_Value = Sum_Value[0] / ((float)Sum_Count[0]);
			break;
		case TOTAL_MAX:
			Calu_Value = max(LastOut_Value[0], Input_Value);
			break;
		case TOTAL_MIN:
			Calu_Value = min(LastOut_Value[0], Input_Value);
			break;
		case TOTAL_T_SUM:
			Calu_Value = LastOut_Value[0] + K * (AI_Last[0] + Input_Value) * dt / 2;
			break;
		}
	}
	if (Sd_Last[0] == false && Sd == true)			//< 上升沿，表示开始积算功能
	{
		//< LastCalu_Value = Calu_Value;			duan0831
		Calu_Value = Init_Value;
		Start_Flg[0] = true;
		Sum_Value[0] = 0;
		Sum_Count[0] = 0;
	}
	else if (Sd_Last[0] == true && Sd == false)		//< 下降沿，停止积算功能
	{
		Start_Flg[0] = false;
		LastCalu_Value[0] = Calu_Value;
	}
	Sd_Last[0] = Sd;
	AI_Last[0] = Input_Value;
	LastOut_Value[0] = Calu_Value;
	/********************************************/
	/**************算法功能实现结束**************/
	/********************************************/	

	/****************运算结果输出**************/
	AO[0] = Calu_Value;
	AO[1] = LastCalu_Value[0];
	/**************运算结果输出完毕************/
	return true;
#undef max
#undef min
}



//************************************
// Method:    	BCPARA							//< 广播SAMA参数变量函数（无参数需要广播的模块直接将BCPara函数设置为NULL即可）
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	int								//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	void ** Data					//< 广播SAMA参数的数据包的指针
//************************************
int BC_PARA(TOTAL)(Model_Base_t* arg, void** Data)
{
	NAME(TOTAL)* Obj = (NAME(TOTAL)*)arg;
	BC_PARA_PUBLIC(Obj);
	return 0;
}



//************************************
// Method:    	BAK_STA							//< 备份SAMA运算中间参数
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	int								//< 成功：返回打包字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 指定模块类型链表的指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int BAK_STA(TOTAL)(Model_Base_t* arg, void** Data)
{
	NAME(TOTAL)* Obj = (NAME(TOTAL)*)arg;
	BAK_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	ANA_STA							//< 解析备份的SAMA运算中间参数
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	int								//< 成功：返回解析字节个数；失败：返回0
// Parameter: 	Model_Base_t * arg				//< 模块参数结构体指针
// Parameter: 	void ** Data					//< 存放数据包当前指针位置的地址
//************************************
int ANA_STA(TOTAL)(Model_Base_t* arg, void** Data)
{
	NAME(TOTAL)* Obj = (NAME(TOTAL)*)arg;
	ANA_STA_PRIVATE(Obj);
	return 0;
}



//************************************
// Method:    	CHANGE_PAR				//< 在线修改模块参数函数
// Programmer:  lww
// Time:		2018/11/16
// Returns:   	int						//< 读取字节长度计数值
// Parameter: 	Model_Base_t* arg		//< 指定模块类型链表的指针
// Parameter: 	void** Data				//< 存放数据包当前指针位置的地址
//************************************
int CHANGE_PAR(TOTAL)(Model_Base_t* arg, void** Data)
{
	int _iLen = 0;
	MEMREAD(((NAME(TOTAL)*)arg)->Par, Data[0]);
	return _iLen;
}



//************************************
// Method:    	INIT_STAPAR						//< 初始化模块运算中间参数
// Programmer:  lww
// Time:		2018/11/16
// Parameter: 	Model_Base_t* arg				//< 模块参数结构体指针
//************************************
void INIT_STAPAR(TOTAL)(Model_Base_t* arg)
{
	NAME(TOTAL)* name = (NAME(TOTAL)*)arg;
	/****************初始化中间变量结构体**************/
	memset(&(name->Sta), 0, sizeof(name->Sta));
	/**************初始化中间变量结构体结束************/

	/****************对中间变量结构体的相关参数进行赋值**************/

	/**************对中间变量结构体的相关参数进行赋值结束************/
}
